﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace LiveNet.Contacts
{
    public class PersonalInfo : DictionaryBase
    {
        #region Private Data
        private bool m_changed = false;
        #endregion

        #region Constructors
        public PersonalInfo()
        {
            BuildDictionary();
        }

        private void BuildDictionary()
        {
            this.Add("FirstName", "");
            this.Add("MiddleName", "");
            this.Add("LastName", "");
            this.Add("UniqueName", "");
            this.Add("SortName", "");
            this.Add("NickName", "");
            this.Add("DisplayName", "");
            this.Add("Birthdate", "");
            this.Add("Anniversary", "");
            this.Add("SpouseName", "");
            this.Add("Gender", "Unspecified");
            this.Add("TimeZone", "None");
        }
        #endregion

        #region Public Methods
        public XmlDocument ToXml(OperationType op)
        {
            XmlDocument xmldoc = new XmlDocument();
            string xml = "<Personal>";
            foreach (DictionaryEntry de in this)
            {
                if ((op == OperationType.Update || op == OperationType.Create) && (de.Key.ToString() == "UniqueName" || de.Key.ToString() == "SortName" || de.Key.ToString() == "DisplayName")) continue;
                xml = xml + "<" + de.Key + ">" + de.Value + "</" + de.Key + ">";
            }
            xml = xml + "</Personal>";
            xmldoc.LoadXml(xml);

            return xmldoc;
        }
        #endregion

        #region Public Properties
        public string FirstName
        {
            get { return this["FirstName"]; }
            set { this["FirstName"] = value.Substring(0, Math.Min(40, value.Length)); }
        }

        public string MiddleName
        {
            get { return this["MiddleName"]; }
            set { this["MiddleName"] = value.Substring(0, Math.Min(40, value.Length)); }
        }

        public string LastName
        {
            get { return this["LastName"]; }
            set { this["LastName"] = value.Substring(0, Math.Min(40, value.Length)); }
        }

        public string UniqueName
        {
            get { return this["UniqueName"]; }
            set { this["UniqueName"] = value.Substring(0, Math.Min(40, value.Length)); }
        }

        public string SortName
        {
            get { return this["SortName"]; }
            set { this["SortName"] = value.Substring(0, Math.Min(120, value.Length)); }
        }

        public string NickName
        {
            get { return this["NickName"]; }
            set { this["NickName"] = value.Substring(0, Math.Min(120, value.Length)); }
        }

        public string DisplayName
        {
            get { return this["DisplayName"]; }
            set { this["DisplayName"] = value.Substring(0, Math.Min(120, value.Length)); }
        }

        public string Birthdate
        {
            get { return this["Birthdate"]; }
            set { this["Birthdate"] = value; }
        }

        public string Anniversary
        {
            get { return this["Anniversary"]; }
            set { this["Anniversary"] = value.Substring(0, Math.Min(10, value.Length)); }
        }

        public string SpouseName
        {
            get { return this["SpouseName"]; }
            set { this["SpouseName"] = value.Substring(0, Math.Min(120, value.Length)); }
        }

        public GenderType Gender
        {
            get { return (GenderType)Enum.Parse(typeof(GenderType), this["Gender"]); }
            set { this["Gender"] = Enum.GetName(typeof(GenderType), value); }
        }

        public TimeZoneType TimeZone
        {
            get { return (TimeZoneType)Enum.Parse(typeof(TimeZoneType), this["TimeZone"]); }
            set { this["TimeZone"] = Enum.GetName(typeof(TimeZoneType), value); }
        }
        #endregion

        #region Dictionary Methods
        public String this[String key]
        {
            get { return ((String)Dictionary[key]); }
            set { Dictionary[key] = value; }
        }

        public ICollection Keys
        {
            get { return (Dictionary.Keys); }
        }

        public ICollection Values
        {
            get { return (Dictionary.Values); }
        }

        public void Add(String key, String value)
        {
            Dictionary.Add(key, value);
        }

        public bool Contains(String key)
        {
            return (Dictionary.Contains(key));
        }

        public void Remove(String key)
        {
            Dictionary.Remove(key);
        }

        protected override void OnInsert(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (value.GetType() != typeof(System.String))
                throw new ArgumentException("value must be of type String.", "value");
        }

        protected override void OnRemove(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");
        }

        protected override void OnSet(Object key, Object oldValue, Object newValue)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (newValue.GetType() != typeof(System.String))
                throw new ArgumentException("newValue must be of type String.", "newValue");
        }

        protected override void OnValidate(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (value.GetType() != typeof(System.String))
                throw new ArgumentException("value must be of type String.", "value");
        }
        #endregion
    }

    public class ProfessionalInfo : DictionaryBase
    {
        #region Private Data
        private bool m_changed = false;
        #endregion

        #region Constructors
        public ProfessionalInfo()
        {
            BuildDictionary();
        }

        private void BuildDictionary()
        {
            this.Add("JobTitle", "");
            this.Add("Profession", "");
            this.Add("Manager", "");
            this.Add("Assistant", "");
        }
        #endregion

        #region Public Methods
        public XmlDocument ToXml(OperationType op)
        {
            XmlDocument xmldoc = new XmlDocument();
            string xml = "<Professional>";
            foreach (DictionaryEntry de in this)
            {
                xml = xml + "<" + de.Key + ">" + de.Value + "</" + de.Key + ">";
            }
            xml = xml + "</Professional>";
            xmldoc.LoadXml(xml);

            return xmldoc;
        }
        #endregion

        #region Public Properties
        public string JobTitle
        {
            get { return this["JobTitle"]; }
            set { this["JobTitle"] = value.Substring(0, Math.Min(120, value.Length)); }
        }

        public string Profession
        {
            get { return this["Profession"]; }
            set { this["Profession"] = value.Substring(0, Math.Min(120, value.Length)); }
        }
        public string Manager
        {
            get { return this["Manager"]; }
            set { this["Manager"] = value.Substring(0, Math.Min(120, value.Length)); }
        }
        public string Assistant
        {
            get { return this["Assistant"]; }
            set { this["Assistant"] = value.Substring(0, Math.Min(120, value.Length)); }
        }
        #endregion

        #region Dictionary Methods
        public String this[String key]
        {
            get { return ((String)Dictionary[key]); }
            set { Dictionary[key] = value; }
        }

        public ICollection Keys
        {
            get { return (Dictionary.Keys); }
        }

        public ICollection Values
        {
            get { return (Dictionary.Values); }
        }

        public void Add(String key, String value)
        {
            Dictionary.Add(key, value);
        }

        public bool Contains(String key)
        {
            return (Dictionary.Contains(key));
        }

        public void Remove(String key)
        {
            Dictionary.Remove(key);
        }

        protected override void OnInsert(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (value.GetType() != typeof(System.String))
                throw new ArgumentException("value must be of type String.", "value");
        }

        protected override void OnRemove(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");
        }

        protected override void OnSet(Object key, Object oldValue, Object newValue)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (newValue.GetType() != typeof(System.String))
                throw new ArgumentException("newValue must be of type String.", "newValue");
        }

        protected override void OnValidate(Object key, Object value)
        {
            if (key.GetType() != typeof(System.String))
                throw new ArgumentException("key must be of type String.", "key");

            if (value.GetType() != typeof(System.String))
                throw new ArgumentException("value must be of type String.", "value");
        }
        #endregion
    }

    public class ProfileCollection
    {
        #region Private Data
        private PersonalInfo m_personal = new PersonalInfo();
        private ProfessionalInfo m_professional;
        #endregion

        #region Constructors
        public ProfileCollection()
        {
        }

        public ProfileCollection(XmlNode xmlnode)
        {
            FromXml(xmlnode);
        }
        #endregion

        #region Public Properties
        public PersonalInfo Personal
        {
            get { return m_personal; }
            set { m_personal = value; }
        }

        public ProfessionalInfo Professional
        {
            get { if (m_professional == null) m_professional = new ProfessionalInfo(); return m_professional; }
            set { m_professional = value; }
        }
        #endregion

        #region Internal Methods
        internal void FromXml(XmlNode xmlnode)
        {
            if (xmlnode == null) return;

            XmlNode nodeParent = xmlnode.SelectSingleNode("Personal");
            if (nodeParent != null)
            {
                Personal = new PersonalInfo();
                XmlNode node = nodeParent.SelectSingleNode("FirstName");
                if (node != null) Personal["FirstName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("MiddleName");
                if (node != null) Personal["MiddleName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("LastName");
                if (node != null) Personal["LastName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("UniqueName");
                if (node != null) Personal["UniqueName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("SortName");
                if (node != null) Personal["SortName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("NickName");
                if (node != null) Personal["NickName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("DisplayName");
                if (node != null) Personal["DisplayName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Birthdate");
                if (node != null) Personal["Birthdate"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Anniversary");
                if (node != null) Personal["Anniversary"] = node.InnerText;
                node = nodeParent.SelectSingleNode("SpouseName");
                if (node != null) Personal["SpouseName"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Gender");
                if (node != null) Personal["Gender"] = node.InnerText;
                node = nodeParent.SelectSingleNode("TimeZone");
                if (node != null) Personal["TimeZone"] = node.InnerText;
            }
            nodeParent = xmlnode.SelectSingleNode("Professional");
            if (nodeParent != null)
            {
                Professional = new ProfessionalInfo();
                XmlNode node = nodeParent.SelectSingleNode("JobTitle");
                if (node != null) Professional["JobTitle"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Profession");
                if (node != null) Professional["Profession"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Manager");
                if (node != null) Professional["Manager"] = node.InnerText;
                node = nodeParent.SelectSingleNode("Assistant");
                if (node != null) Professional["Assistant"] = node.InnerText;
            }
        }
        #endregion

        #region Public Methods
        public XmlDocument ToXml(OperationType op)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(string.Format("<Profiles>{0}{1}</Profiles>", Personal.ToXml(op).InnerXml, Professional.ToXml(op).InnerXml));
            return xmldoc;
        }
        #endregion
    }
}
